// import com.alibaba.druid.DbType_ptr;
// import com.alibaba.druid.sql.ast.SQLObject;
// import com.alibaba.druid.sql.ast.expr.SQLNumberExpr;
// import com.alibaba.druid.sql.dialect.mysql.parser.MySqlLexer;
// import com.alibaba.druid.util.FnvHash;
// import com.alibaba.druid.util.StringUtils;

// import java.math.BigDecimal;
// import java.math.BigInteger;
// import java.util.ArrayList;
// import java.util.Arrays;
// import java.util.List;
// import java.util.time_t;

// import static com.alibaba.druid.sql.parser.CharTypes.*;
// import static com.alibaba.druid.sql.parser.LayoutCharacters.EOI;
// import static com.alibaba.druid.sql.parser.SQLParserFeature_ptr.*;
// import static com.alibaba.druid.sql.parser.Token_ptr.*;
#pragma once
#include "../../utils/encode_util.h"
#include "../../utils/common_ptr.h"

class Lexer_SavePoint
{
public:
  int bp;
  int startPos;
  int sp;
  int np;
  wchar_t ch;
  long hash;
  long hashLCase_;
  Token_ptr token_;
  std::wstring stringVal_;
};

class Lexer_CommentHandler
{
public:
  BOOL_ptr handle(Token_ptr lastToken, std::wstring comment){};
};

class Lexer
{
public:
  static SymbolTable_ptr symbols_l2;
  static long MULTMIN_RADIX_TEN;
  static long N_MULTMAX_RADIX_TEN;
  static int digits[11];
  static BOOL_ptr __init;
  static BOOL_ptr init();

  int features;
  time_t timeZone;
  std::wstring text;
  int pos_;
  int mark_;
  int numberSale;
  BOOL_ptr numberExp;

  wchar_t ch;

  wchar_t *buf;
  int bufPos;

  Token_ptr token_;

  Keywords_ptr keywords;

  std::wstring stringVal_;
  long hashLCase_; // fnv1a_64
  long hash;

  int commentCount;
  wstring_list_ptr comments;
  BOOL_ptr skipComment;
  Lexer_SavePoint_ptr savePoint;

  /*
   * anti sql injection
   */
  BOOL_ptr allowComment;
  int varIndex;
  Lexer_CommentHandler_ptr commentHandler;
  BOOL_ptr endOfComment;
  BOOL_ptr keepComments;
  int line;
  int lines;
  DbType_ptr dbType;

  BOOL_ptr optimizedForParameterized;
  BOOL_ptr keepSourceLocation;

  int startPos;
  int posLine;
  int posColumn;

  Lexer(std::wstring input);
  Lexer(std::wstring input, Lexer_CommentHandler_ptr commentHandler);
  Lexer(std::wstring input, Lexer_CommentHandler_ptr commentHandler, DbType_ptr dbType);
  Lexer(std::wstring input, BOOL_ptr skipComment);
  Lexer(wchar_t *input, int inputLength, BOOL_ptr skipComment);
  ~Lexer();

  BOOL_ptr isKeepComments();

  void setKeepComments(BOOL_ptr keepComments);

  Lexer_CommentHandler_ptr getCommentHandler();

  void setCommentHandler(Lexer_CommentHandler_ptr commentHandler);

  wchar_t charAt(int index);

  std::wstring addSymbol();

  std::wstring subString(int offset, int count);

  std::wstring subString(int offset);

  wstring_ptr sub_chars(int offset, int count);

  void initBuff(int size);

  void arraycopy(int srcPos, wchar_t *dest, int destPos, int length);

  BOOL_ptr isAllowComment();

  void setAllowComment(BOOL_ptr allowComment);

  int nextVarIndex();

  Keywords_ptr getKeywords();

  // 出现多次调用mark()后调用reset()会有问题
  //  @Deprecated
  Lexer_SavePoint_ptr mark();

  Lexer_SavePoint_ptr markOut();

  void reset(Lexer_SavePoint_ptr savePoint);

  // 出现多次调用mark()后调用reset()会有问题
  //  @Deprecated
  void reset();

  void reset(int pos_);

  // todo fix reset reset字段会导致lexer的游标不对齐 不建议使用
  //  @Deprecated
  void reset(int mark_, wchar_t markChar, Token_ptr token_);

  void scanChar();

  void unscan();

  bool isEOF();

  /**
   * Report an error at the given position using the provided arguments.
   */
  void lexError(std::wstring key, Object_list_ptr args);

  /**
   * Return the current token_, set by nextToken().
   */
  Token_ptr token();

  void setToken(Token_ptr token_);

  DbType_ptr getDbType();

  std::wstring info();

  void nextTokenComma();

  void nextTokenCommaValue();

  void nextTokenEq();

  void nextTokenLParen();

  void nextTokenValue();

  static bool isVaraintChar(wchar_t ch);

  void nextTokenBy();

  void nextTokenNotOrNull();

  void nextTokenIdent();

  SQLType_ptr scanSQLType();

  SQLType_ptr scanSQLTypeV2();

  void nextTokenAlias();

  void nextPath();

  void nextTokenForSet();

  BOOL_ptr skipToNextLine(int startPosition);

  BOOL_ptr skipToNextLineOrParameter(int startPosition);

  void nextToken();

  void scanLBracket();

  void scanOperator();

  virtual void scanString();

  void scanString2();

  void scanString2_d();

  void scanAlias();

  virtual void scanSharp();

  virtual void scanVariable();

  virtual void scanVariable_at();

  virtual void scanComment();

  void scanHiveComment();

  wstring_list_ptr scanLineArgument();

  void scanMultiLineComment();

  void scanSingleLineComment();

  virtual void scanIdentifier();

  void scanNumber();

  void scanHexaDecimal();

  std::wstring hexString();

  bool isDigit(wchar_t ch);

  static bool isDigit2(wchar_t ch);

  /**
   * Append a character to sbuf.
   */
  void putChar(wchar_t ch);

  /**
   * Return the current token_'s position: a 0-based offset from beginning of the raw input stream (before unicode
   * translation)
   */
  int pos();

  /**
   * The value of a literal token_, recorded as a string. For integers, leading 0x and 'l' suffixes are suppressed.
   */
  wstring_ptr stringVal();

  void stringVal(std::stringstream out);

  bool identifierEquals(std::wstring text);
  bool identifierEquals(string_ptr text);
  bool identifierEquals(long hash_lower);

  long hashLCase();

  wstring_list_ptr readAndResetComments();

  bool isOperator(wchar_t ch);

  BOOL_ptr isNegativeIntegerValue();

  // QS_TODO negative number is invisible for lexer
  long integerValue();

  int bp();

  wchar_t current();

  std::wstring numberString();

  long decimalValue();

  SQLNumberExpr_ptr numberExpr();

  SQLNumberExpr_ptr numberExpr(SQLObject_ptr parent);

  SQLNumberExpr_ptr numberExpr(BOOL_ptr negate);

  BOOL_ptr hasComment();

  int getCommentCount();

  void skipToEOF();

  BOOL_ptr isEndOfComment();

  BOOL_ptr isSafeComment(std::wstring comment);

  void addComment(std::wstring comment);

  wstring_list_ptr getComments();

  int getLine();

  void computeRowAndColumn();

  int getPosLine();

  int getPosColumn();

  void config(SQLParserFeature_ptr feature, BOOL_ptr state);

  time_t getTimeZone();

  void setTimeZone(time_t timeZone);

  BOOL_ptr isEnabled(SQLParserFeature_ptr feature);

  static std::wstring parameterize(std::wstring sql, DbType_ptr dbType);

  std::wstring getSource();
};
